<!DOCTYPE html>
<html>
<body>

<?php
	class RsaService
{
    /**
     * 公钥
     * @var
     */
    protected $public_key="";


    /**
     * 私钥
     * @var
     */
    protected $private_key="";


    /**
     * 公钥文件路径
     * @var
     */
    protected $public_key_path = 'keys/rsa_public_key.pub';


    /**
     * 采用pkcs8只是为了方便程序解析
     * 私钥文件路径
     * @var
     */
    protected $private_key_path = 'keys/rsa_private_key_pkcs8.pem';


    /**
     * 初始化配置
     * RsaService constructor.
     * @param bool $type 默认私钥加密
     */
    public function __construct($type = true)
    {
        if ($type) {
            $this->private_key = $this->formatPriKey( $this->private_key);
            $this->private_key = $this->getPrivateKey();
        } else {
            $this->public_key = $this->formatPubKey($this->public_key);
            $this->public_key = $this->getPublicKey();
        }
    }

    /**********************************私钥格式化*************************************/
    private function formatPriKey($priKey) {
        $fKey = "-----BEGIN PRIVATE KEY-----\n";

        $len = strlen($priKey);

        for($i = 0; $i < $len; ) {
             $fKey = $fKey . substr($priKey, $i, 64) . "\n";
           $i += 64;
        }

        $fKey .= "-----END PRIVATE KEY-----";

        return $fKey;
}

 /**********************************公钥格式化*************************************/
private function formatPubKey($pubKey) {
         $fKey = "-----BEGIN PUBLIC KEY-----\n";
         $len = strlen($pubKey);
         for($i = 0; $i < $len; ) {
             $fKey = $fKey . substr($pubKey, $i, 64) . "\n";
             $i += 64;
         }
         $fKey .= "-----END PUBLIC KEY-----";
         return $fKey;
}

    /**
     * 配置私钥
     * openssl_pkey_get_private这个函数可用来判断私钥是否是可用的，可用，返回资源
     * @return bool|resource
     */
    private function getPrivateKey()
    {
        $original_private_key = $this->private_key;
        return openssl_pkey_get_private($original_private_key);
    }


    /**
     * 配置公钥
     * openssl_pkey_get_public这个函数可用来判断私钥是否是可用的，可用，返回资源
     * @return resource
     */
    public function getPublicKey()
    {
        $original_public_key = $this->public_key;
        return openssl_pkey_get_public($original_public_key);
    }


    /**
     * 私钥加密
     * @param $data
     * @param bool $serialize 是为了不管你传的是字符串还是数组，都能转成字符串
     * @return string
     * @throws \Exception
     */
    public function privateEncrypt($data, $serialize = true)
    {
        openssl_private_encrypt(
            $serialize ? serialize($data) : $data,
            $encrypted, $this->private_key
        );

        if ($encrypted === false) {
            throw new \Exception('Could not encrypt the data.');
        }

        return base64_encode($encrypted);
    }


    /**
     * 私钥解密
     * @param $data
     * @param bool $unserialize
     * @return mixed
     * @throws \Exception
     */
    public function privateDecrypt($data, $unserialize = true)
    {
        openssl_private_decrypt(base64_decode($data),$decrypted, $this->private_key);

        if ($decrypted === false) {
            throw new \Exception('Could not decrypt the data.');
        }
		echo $decrypted;
		return $decrypted;
        // return $unserialize ? unserialize($decrypted) : $decrypted;
    }


    /**
     * 公钥加密
     * @param $data
     * @param bool $serialize 是为了不管你传的是字符串还是数组，都能转成字符串
     * @return string
     * @throws \Exception
     */
    public function publicEncrypt($data, $serialize = false)
    {
        openssl_public_encrypt(
            $serialize ? serialize($data) : $data,
            $encrypted, $this->public_key
        );

        if ($encrypted === false) {
            throw new \Exception('Could not encrypt the data.');
        }

        return base64_encode($encrypted);
    }


    /**
     * 公钥解密
     * @param $data
     * @param bool $unserialize
     * @return mixed
     * @throws \Exception
     */
    public function publicDecrypt($data, $unserialize = true)
    {

        openssl_public_decrypt(base64_decode($data),$decrypted, $this->public_key);

        if ($decrypted === false) {
            throw new \Exception('Could not decrypt the data.');
        }

        return $unserialize ? unserialize($decrypted) : $decrypted;
    }
    /**
     * 生成签名
     * @param    string     $signString 待签名字符串
     * @return   string     base64结果值
     */
    public function getSign($signString){
        $signature = '';
        echo $signString;
        openssl_sign($signString, $signature, $this->private_key,OPENSSL_ALGO_MD5);
        return base64_encode($signature);
    }
    
    /**
     * 校验签名
     * @param    string     $sign   签名
     * @param    string     $toSign 待签名字符串
     * @return   bool
     */
    function checkSign($sign,$toSign){
        $result = openssl_verify($toSign, base64_decode($sign), $this->public_key,OPENSSL_ALGO_MD5);
        return $result === 1 ? true : false;
    }

}


// 1、解密
// $encryptedJson="";
// $rsa = new RsaService(true);
// $res=$rsa->privateDecrypt(urldecode($encryptedJson));
// echo $res;

// 2、加密
// $rsa = new RsaService(false);
// $res=$rsa->publicEncrypt("123456789");
// echo $res;


// 3、签名
// $s1 = "123456";
// $rsa = new RsaService(true);
// $res=$rsa->getSign($s1);
// echo $res;

// 4、验签
$rsa = new RsaService(false);
$toSign = "123456@abc";
$signString = "Qp+6L6A2sVJ8L4CwHTRZcVACuCYvFfP5rT4AwDQyTun87LBLjFG/KknHjPOG0u5+ISRzw/wcnPb5oIuUm2/oca9ccH48NqeqE637ZKKI+3//tqhMeZ98Jr0kwxDCNQqsSKYPWZKiOzaVSK+1Kc88pHmzUpdkpXbJdubRaqU+byY=";
$res = $rsa->checkSign($signString, $toSign);
if ($res) {
    echo "ok";
} else {
    echo "fail";
}
?>

</body>
</html>
